package com.niodata.dp.web.module.task;

import com.niodata.dp.core.OwnerType;
import com.niodata.dp.core.exception.ErrorCodes;
import com.niodata.dp.core.resource.Resource;
import com.niodata.dp.core.resource.ResourceType;
import com.niodata.dp.core.resource.ResourceType.TaskConfType;
import com.niodata.dp.core.resource.Resources;
import com.niodata.dp.core.service.SystemServices;
import com.niodata.dp.core.usermgr.model.GroupInfo;
import com.niodata.dp.core.usermgr.model.UserInfo;
import com.niodata.dp.core.usermgr.op.GroupInfoService;
import com.niodata.dp.task.entity.TaskConf;
import com.niodata.dp.task.service.TaskConfManager;
import com.niodata.dp.util.IdUtil;
import com.niodata.dp.web.module.base.BaseController;
import com.niodata.dp.web.security.ContextUtil;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by ndp on 17-8-17.
 */
@RestController("TaskConfController")
@RequestMapping("/v1/task")
public class TaskConfController extends BaseController {

  @Autowired
  @Qualifier("taskConfManagerImpl")
  TaskConfManager taskConfManager;

  @Autowired
  @Qualifier("DpUserMgrGroup")
  private GroupInfoService groupInfoService;

  /**
   * createTaskConf.
   *
   * @param taskConf TaskGraph
   * @return object
   */
  @RequestMapping(value = {"/admin/conf"}, method = {RequestMethod.POST})
  public Object createTaskConf(@RequestBody TaskConf taskConf) throws IOException {
    UserInfo userInfo = ContextUtil.getCurrentUser();
    if (OwnerType.PUBLIC.name().equals(taskConf.getOwnerType())) {
      taskConf.setOwnerType(OwnerType.GROUP.name());
      GroupInfo publicGroup = this.groupInfoService.getGroupInfo("All");
      taskConf.setOwnerId(publicGroup.getGroupId());
    } else if (OwnerType.USER.name().equals(taskConf.getOwnerType())) {
      taskConf.setOwnerType(OwnerType.USER.name());
      taskConf.setOwnerId(userInfo.getUserId());
    } else if (OwnerType.GROUP.name().equals(taskConf.getOwnerType())) {
      taskConf.setOwnerType(OwnerType.GROUP.name());
      taskConf.setOwnerId(taskConf.getOwnerId());
    } else {
      throw new RuntimeException("param error");
    }
    taskConf.setId(IdUtil.uuid());
    taskConf.setOwnerName(userInfo.getLoginName());
    this.operationAccessControl
          .checkServicePermission(userInfo.getUserId(), OwnerType.valueOf(taskConf.getOwnerType()),
                taskConf.getOwnerId(),
                SystemServices.getSystemService(ResourceType.TaskConf.getTypeName()));
    this.taskConfManager.createTaskConf(taskConf);
    return getResult(true);
  }

  @RequestMapping(value = "/admin/conf", method = RequestMethod.PUT)
  public Object updateTask(@RequestBody TaskConf taskConf) {
    UserInfo userInfo = ContextUtil.getCurrentUser();
    Resource resource = Resources
          .newResource(ResourceType.TaskConf, taskConf.getId());
    this.operationAccessControl.checkPermission(resource, userInfo, TaskConfType.Update);
    this.taskConfManager.updateTaskConf(taskConf);
    return this.getResult(true);
  }

  @RequestMapping(value = {"/admin/conf"}, method = {RequestMethod.DELETE})
  public Object deleteTask(@RequestParam("id") String id) {
    Resource resource = Resources.newResource(ResourceType.TaskConf, id);
    this.operationAccessControl
          .checkPermission(resource, ContextUtil.getCurrentUser(), TaskConfType.Delete);
    taskConfManager.deleteTaskConfById(id);
    return getResult(true);
  }

  /**
   * getTasksList.
   *
   * @param pageIndex pageIndex
   * @param pageSize pageSize
   * @param ownerId owner id (userid or groupid)
   * @param ownerTypeStr owner type(USER,GROUP,PUBLIC)
   * @return Object
   */
  @RequestMapping(value = {"/view/conf"}, method = {RequestMethod.GET})
  public Object getTasksList(
        @RequestParam(value = "pageIndex", required = false, defaultValue = "1") int pageIndex,
        @RequestParam(value = "pageSize", required = false, defaultValue = "20") int pageSize,
        @RequestParam(value = "keyWord", required = false) String keyWord,
        @RequestParam(value = "ownerType", required = false) String ownerTypeStr,
        @RequestParam(value = "ownerId", required = false) Long ownerId) {
    if (keyWord != null && keyWord.length() == 0) {
      keyWord = null;
    }
    OwnerType ownerType = null;
    if (ownerTypeStr != null && ownerTypeStr.length() > 0) {
      ownerType = OwnerType.valueOf(ownerTypeStr);
    }
    int offset = (pageIndex - 1) * pageSize < 0 ? 0 : (pageIndex - 1) * pageSize;
    if (offset < 0 || pageSize < 1) {
      return getError(ErrorCodes.ERROR_PARAM, "offset/count param error");
    }
    List<TaskConf> taskConfList = null;
    UserInfo userInfo = ContextUtil.getCurrentUser();
    if (OwnerType.USER.equals(ownerType)) {
      taskConfList = taskConfManager
            .getUserTaskConf(userInfo.getUserId(), keyWord, offset, pageSize + 1);
    } else if (OwnerType.GROUP.equals(ownerType)) {
      if (ownerId == null) {
        GroupInfo groupInfo = groupInfoService.getGroupInfo("All");
        ownerId = groupInfo.getGroupId();
      }
      taskConfList = taskConfManager.getGroupTaskConf(userInfo.getUserId(),
            ownerId, keyWord, offset, pageSize + 1);
    } else {
      taskConfList = taskConfManager.getUserAuthorizedTaskConf(userInfo.getUserId(),
            keyWord, offset, pageSize + 1);
    }
    boolean hasMore = taskConfList.size() > pageSize;
    Map<String, Object> resultMap = new HashMap<>();
    resultMap.put("pageIndex", pageIndex);
    resultMap.put("start", pageIndex <= 1 && taskConfList.size() == 0 ? 0 : offset + 1);
    resultMap.put("stop", hasMore ? offset + pageSize : offset + taskConfList.size());
    resultMap.put("hasMore", hasMore);
    if (hasMore) {
      taskConfList.remove(taskConfList.size() - 1);
    }
    return getResult(taskConfList, resultMap);
  }
}
